vscode: codelens-driven review comments in the builder diff — per-builder queue with batched submit to PTY (#1037) - #1382
Conversation
…ste, exclude block
…c, info/exclude block
…le-bar toggle, always-on context menu
…ile, edit/delete
…TY, status-bar counter, wiring
…menting ranges on registry change
…ts after the last line
…e highlight covers every line
…minal-manager deviation, note reload gap
…nges, queue preload at activation, echo-suppression + clamp tests
Architect ReviewAPPROVE (pr gate; merge awaits Amr's authorization per workspace policy). The post-consult fixes (945e3b4) — independently verified per the escalation, all three real:
Plan-decision spot-checks from the gate guidance: the gitignore mechanism landed as an idempotent Process note worth its own line: this consult almost got skipped on an OpenAI billing failure, with 'proceed on claude-APPROVE alone' as the tempting option. The restored lane returned three real findings against a claude APPROVE — the window's 'majority APPROVE is not consensus / codex is the dominant real-blocker' lesson, re-demonstrated on the first opportunity. Architect review |
PIR Review: Codelens-Driven Review Comments in the Builder Diff (per-builder queue + batched submit)
Fixes #1037
Summary
The builder diff gains a structured review-comment surface layered on #789's fire-and-forget PTY injection: the reviewer composes comments in inline VSCode comment threads (codelens, gutter "+", or context menu), the comments persist in a per-builder queue at
.builders/<id>/.codev/pending-comments.json, and a singleSubmit Reviewaction (status-bar button + palette command) packages the whole queue into one markdown message typed into the builder PTY's prompt buffer, wrapped in bracketed-paste escapes, with no Enter pressed — the human reviews and sends. The codelens shows exactly one action per anchor, controlled bycodev.diffCodelensMode(defaultforward, so existing #789 users see zero change; comment mode is a per-workspace opt-in via the diff title-bar toggle). The panel display surface for the queue is explicitly out of scope — it belongs to #1049, which will consume this PR'sReviewQueueStoreread + event API.Files Changed
apps/vscode/package.json(+132 / -0): setting, 10 commands, title-bar toggle, context-menu, comments menusapps/vscode/src/review-queue/queue.ts(+169, new): pure schema / packaging / bracketed paste / exclude blockapps/vscode/src/review-queue/store.ts(+252, new): per-builder fs persistence, watcher sync, info/exclude writeapps/vscode/src/review-queue/reconcile.ts(+75, new): pure thread-reconcile planningapps/vscode/src/review-queue/submit.ts(+112, new): Submit Review / Discard flowsapps/vscode/src/review-queue/status-bar.ts(+45, new):Submit Review (N)counterapps/vscode/src/comments/builder-review.ts(+365, new): comment controller, input via built-in addComment, mount/reconcile, edit/deleteapps/vscode/src/diff-inject-codelens.ts(+64 / -~10): mode-aware lenses, mode context key, registry entries accessorapps/vscode/src/diff-inject-ref.ts(+27 / -~10):LensDescriptor.range+ label parameterapps/vscode/src/extension.ts(+53 / -~13): wiring, new commands, forward-selection cursor fallbackcodev/plans/1037-vscode-codelens-driven-review-.md,codev/state/pir-1037_thread.mdCommits
35b79381[PIR vscode: codelens-driven review comments in the unified diff editor — per-builder queue with batched submit to PTY (follow-up to #789) #1037] Pure review-queue module: schema, packaging, bracketed paste, exclude block9e15670a[PIR vscode: codelens-driven review comments in the unified diff editor — per-builder queue with batched submit to PTY (follow-up to #789) #1037] ReviewQueueStore: per-builder fs persistence, watcher sync, info/exclude blockca3ee865[PIR vscode: codelens-driven review comments in the unified diff editor — per-builder queue with batched submit to PTY (follow-up to #789) #1037] Mode-aware diff codelenses: diffCodelensMode setting, title-bar toggle, always-on context menu9aafea09[PIR vscode: codelens-driven review comments in the unified diff editor — per-builder queue with batched submit to PTY (follow-up to #789) #1037] Builder-review comment controller: inline threads, reconcile, edit/deletef0383162[PIR vscode: codelens-driven review comments in the unified diff editor — per-builder queue with batched submit to PTY (follow-up to #789) #1037] Submit Review: batched bracketed-paste flush to builder PTY, status-bar counter, wiring67cb80d0[PIR vscode: codelens-driven review comments in the unified diff editor — per-builder queue with batched submit to PTY (follow-up to #789) #1037] Focus comment input on codelens click via built-in addComment commandf58047ff[PIR vscode: codelens-driven review comments in the unified diff editor — per-builder queue with batched submit to PTY (follow-up to #789) #1037] Comment input: pass range args to addComment, refresh commenting ranges on registry change24ba4610[PIR vscode: codelens-driven review comments in the unified diff editor — per-builder queue with batched submit to PTY (follow-up to #789) #1037] Mount queued threads on their full range so the widget sits after the last line1f8e3218[PIR vscode: codelens-driven review comments in the unified diff editor — per-builder queue with batched submit to PTY (follow-up to #789) #1037] Extend thread ranges to last-line content end so the range highlight covers every linea094352e[PIR vscode: codelens-driven review comments in the unified diff editor — per-builder queue with batched submit to PTY (follow-up to #789) #1037] Flip diffCodelensMode default to forward (preserve vscode: inject file/hunk reference into builder PTY from the unified-diff editor (codelens) #789 for existing users)Test Results
pnpm build(porch check): passvitest): 695 tests / 60 files passing (38 new across 6 new test files + extensions to 2 existing)pnpm check-types+eslint: cleanDeviations From the Approved Plan
forward, notcomment— human decision at the dev-approval gate (2026-08-10), deliberately overriding the issue's "comment is the default": existing vscode: inject file/hunk reference into builder PTY from the unified-diff editor (codelens) #789 users see zero behavior change; comment mode is opt-in per workspace. This also removed the need for a behavior-change changelog warning.workbench.action.addComment(args-based) instead of programmatically created threads — the stable API cannot focus a created thread's input. Whole-file comments use the nativefileCommentconcept (thread.range === undefined).lineRangeis nullable in the schema (null = whole-file comment) so the packaged section header reads### pathinstead of a fabricated line ref.Cmd/Ctrl+K Bkeybinding keeps its original selection guard.apps/vscode/CHANGELOG.mdanddocs/releases/UNRELEASED.mdare maintained on thedocs/vscode-changelogbranch per that workflow; suggested entry handed to the architect: "Builder diff review comments: compose queued review comments in inline threads (opt-in comment mode via the diff title-bar toggle), batch-submit to the builder's prompt via Submit Review."terminal-manager.tsunchanged — the plan listed aninjectBuilderTextMultilinemethod; insteadsubmit.tswraps the message withwrapBracketedPasteat the call site and reuses the existinginjectBuilderText, leaving the vscode: inject file/hunk reference into builder PTY from the unified-diff editor (codelens) #789 injection path byte-identical. (Flagged by the PR consultation as an undocumented deviation; documented here.)workbench.action.addCommentvalidates against the provider's commenting ranges, so a comment-mode-only provider broke the always-visible context-menuComment for Builderin forward mode, the shipped default. Ranges are now provided for registered builder-diff files in every mode (regression-pinned inbuilder-review-ranges.test.ts); the codelens remains the mode-distinct surface.Architecture Updates
Routed COLD: added a "Builder review-comment queue (#1037)" entry to
codev/resources/arch.mdunder VS Code Extension → Key Design Decisions (storage location + single-owner store + the #789/#1037 never-merge-state invariant + the #1049 seam). Nothing HOT: the feature is extension-scoped, not a cross-cutting system-shape fact that changes implementation choices elsewhere.Lessons Learned Updates
Routed COLD: three
[From 1037]entries incodev/resources/lessons-learned.mdunder UI/UX — (1) programmaticCommentThreadcreation cannot focus its input; open inputs viaworkbench.action.addCommentwith{range}/{fileComment}args; (2) VS Code caches a document's commenting ranges and only re-queries on its own triggers; re-assigncommentingRangeProviderto force a recompute when eligibility changes after the editor opened; (3) a thread range ending at column 0 excludes its last line from the range highlight, and the widget renders after the range's last line. Nothing HOT: all three are VS Code comments-API recipes, not cross-cutting rules.Things to Look At During PR Review
review-queue/store.tsmutate path: load-mutate-write folds in concurrent writers from other windows; the watcher echo-suppression compares against last-written bytes. Worth a read for race assumptions.queue.ts wrapBracketedPaste+submit.ts):\n→\rconversion inside\x1b[200~ … \x1b[201~. Verified live at dev-approval against a real Claude REPL; the wrapped payload travelssendText→ Tower WebSocket → PTY stdin.info/excludemanaged block (store.ts ensureExclude): writes to$GIT_COMMON_DIR/info/excluderesolved viagit rev-parse; the.builder-*family glob also silences spawn scaffolding files. Failures are deliberately swallowed (cosmetic concern, never blocks a comment write).comments/builder-review.ts: the commenting-ranges refresh trick (provider re-assignment) and the reconciler's mount/dispose lifecycle are the least obvious parts; the pure planner (reconcile.ts) carries the tests.codev.forwardToBuilderand the keybinding are unchanged; the only vscode: inject file/hunk reference into builder PTY from the unified-diff editor (codelens) #789-adjacent edits are the context-menuwhenrelaxation + cursor fallback (deviation 4) and lens titles/commands swapping by mode.workbench.action.addCommentvalidates against them; with forward as the shipped default,Codev: Comment for Builderfrom the context menu could not create a thread. Fixed by making the ranges mode-independent (deviation 7); regression testbuilder-review-ranges.test.tspins ranges +enableFileCommentsin every mode.ReviewQueueStore.preloadFromDisk()scans.builders/*/.codev/pending-comments.jsonat activation, so the palette command and status-bar counter see queues before any diff opens. Covered by two new store tests.clampAnchorLinesinreconcile.ts, 5 cases).How to Test Locally
pnpm install; launch the extension host fromapps/vscode(F5) orpnpm vsixand install.Forward to Builderand behave exactly as vscode: inject file/hunk reference into builder PTY from the unified-diff editor (codelens) #789.$(comment)toggle: lenses flip toComment for Builder, gutter "+" appears. Add comments via lens, gutter, and right-click; watch the status-barSubmit Review (N)counter.Codev: Submit Review: packaged message lands in the builder's prompt buffer without submitting; queue and threads clear; press Enter in the terminal to deliver..builders/<id>/.codev/pending-comments.jsonstays separate; each submit flushes only its builder.git statusinside a builder worktree: neither the queue file nor.builder-*scaffolding shows as untracked.